图解线程生命周期
小伙伴们晚上好呀~ 😋
「4ye」 这期来和大家分享下这个 「Java线程的生命周期」 ( •̀ ω •́ )y
注意这里特意指明了是 「Java」
因为线程这东西是 「操作系统调度的最小单元」
所以在操作系统中肯定也有它的生命周期呀,各种状态呀~
让我们一起往下看看叭👇
操作系统线程生命周期
如图所示~ ,这些也被称为 「通用线程状态」
分为五种:
❝「初始状态、可运行状态、运行状态、休眠状态和终止状态」
❞
初始状态
这里仅仅是 编程语言上的创建,操作系统中并没有创建线程。
可运行状态
操作系统中已经成功创建线程了,「等待获取CPU时间片」了
运行状态
还记得之前讲到进程的调度算法吗😄,线程是进程的基本组成单元,当进程被调度时,也意味着对应的线程被执行啦~ (操作系统从就绪队列中取出任务,然后为其分配一定的时间片去执行~)
这里线程就变成运行状态了 ,正在 「消耗CPU时间片」
休眠状态
比如 阻塞IO 或者 等待某个事件时 ,就会导致线程的状态变成休眠状态,此时 CPU 会浪费在等待上
要等到IO结束,或着等到了某个事件,线程才会变成可运行状态
终止状态
线程已经执行完了,或者出现异常也会进入终止状态,此时不能再切换成其他状态了,「线程的生命周期结束了」
简单介绍完这个操作系统的生命周期,让我们来看看这个 java中线程的生命周期叭~
Java线程的生命周期
直接上图~
在 Thread
源码中,可以发现枚举类 State
中定义了下面几种状态
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
NEW
对应创建线程,未调用 start()
方法时候的状态
Thread thread = new Thread();
RUNNABLE
调用了 start()
方法的线程会进入该状态,
Thread thread = new Thread();
thread.start();
BLOCKED
当进入 Synchronized
同步代码块或者方法时,没有获取到锁的🔒,就会进入阻塞状态,此时线程会进入该锁对象的 「同步队列」 中,这里也十分有趣!哈哈哈 后面写这个 [[ Synchronized 锁的实现原理]] 时带大家一起看看😝
获取到锁后就进入 RUNNABLE
状态啦。
public class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
hello();
}
public void hello() {
synchronized ("Java4ye") {
System.out.println(Thread.currentThread().getName() + " : Java4ye");
while (true) {
}
}
}
public static void main(String[] args) {
new MyThread("A").start();
new MyThread("B").start();
new MyThread("C").start();
}
}
效果:
WAITING
这里调用 Object
类的 wait
方法 或者 Thread
类的 join
方法,将会导致线程 「释放锁」,进入该对象的 「等待队列」,同时线程变为等待状态。
或者使用 LockSupport.park();
也会进入 WAITING
状态 。
这个 LockSupport
是一个很灵活的「线程工具类」,嘿嘿 后面也会单独介绍这个 [[LockSupport ]] 😝
比如
public void hello() {
synchronized ("Java4ye") {
System.out.println(Thread.currentThread().getName() + " : Java4ye");
try {
"Java4ye".wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("End");
}
}
当调用 Object
类的 notify
或者 notifyAll
方法时,线程会重新进入RUNNABLE
状态。
调用 LockSupport.unpark(myThread);
myThread
线程会重新进入 RUNNABLE
状态。
TIMED_WAITING
这里就比较简单啦,在上面的等待方法中加一个时间~
比如 Object.wait(long)
, Thread.join(long)
等等 如上图所示~
最主要的是 Thread.sleep(long)
方法不会释放锁 ,Object.wait(long)
会释放锁资源
时间到了之后,线程重新进入 RUNNABLE
状态 ,
TERMINATED
线程执行完成,就进入该状态了,不能再转成其他状态了
总结
对比下 「操作系统和Java中线程的生命周期」 ,可以发现
「操作系统的可运行状态和运行状态对应 Java 中的 Runnable 状态」 「操作系统的休眠状态,对应 Java 中的三种状态 BLOCKED, WAITING, TIMED_WAITING」
如下~
回顾
嘿嘿 到这里 「4ye」 已经和小伙伴们分享这四个啦 冲冲冲!😝
「我是 4ye 我们下期再见啦 ヾ( ̄▽ ̄)Bye~~ Bye ~~」
Java中的锁居然有这么多!
面试官:线程有几种创建方式?
时间片,上下文,调度算法等知识点~
带你从CPU看到进程~(硬核)